<template>
    <el-form :inline="true">
        <el-form-item prop="roleKey">
            <el-space :fill="false">
                <el-button
                    type="primary"
                    plain
                    icon="Plus"
                    @click="startInsert('')"
                ></el-button>
                <el-input
                    placeholder="请输入查询字符"
                    clearable
                    :prefix-icon="Search"
                    v-model="searchPrefix"
                />
                <el-select v-model="searchLimit" placeholder="Select" style="width: 80px">
                    <el-option
                        v-for="item in searchLimitOptions"
                        :key="item.key"
                        :label="item.label"
                        :value="item.value"
                    />
                </el-select>
                <el-button type="primary" icon="Search" @click="search()"></el-button>

            </el-space>
        </el-form-item>
    </el-form>

    <el-table
        stripe
        :show-header="false"
        :data="tableData"
        row-key="key"
        @row-click="handleRowClick"

    >
        <!--    <el-table-column type="selection" width="55" :selectable="selectable" />-->
        <!--    <el-table-column prop="key" label="key" hidden="hidden" />-->
        <el-table-column prop="name" label="key" min-width="180">
            <template #default="scope">
                <el-space>
                <el-icon v-if="!!scope.row.lease">
                    <Clock/>
                </el-icon>
                <el-icon v-if="!!!scope.row.lease">
                    <Document/>
                </el-icon>
                <span>{{ scope.row.name }}</span>
                </el-space>
            </template>
        </el-table-column>
<!--        <el-table-column prop="lease" label="lease" />-->
        <!--      <el-table-column prop="createdIndex" label="created" />-->
        <!--      <el-table-column prop="modifiedIndex" label="modified" />-->
        <el-table-column label="Operations" min-width="120" align="right">
            <template #default="scope">
                <el-button link type="primary" size="small" icon="View" @click="startDetail(scope.row)"
                           :disabled=scope.row.dir></el-button>
                <!--          <el-button link type="primary" size="small" icon="Plus" @click="startInsert(scope.row.key)" :disabled=!scope.row.dir ></el-button>-->
                <!--          <el-button link type="primary" size="small" icon="Edit" @click="startEdit(scope.row)" :disabled=scope.row.dir ></el-button>-->
                <el-button link type="primary" size="small" icon="Delete" @click="startDelete(scope.row)"></el-button>
            </template>
        </el-table-column>
    </el-table>
    <el-dialog
        v-model="insertDialog"
        title="新增/编辑节点信息"
        width="500"
    >
        <el-form :model="insertForm">
            <el-form-item v-if="insertForm.showName" label="name" prop="name">
                <el-input v-model="insertForm.name" placeholder="当前目录下添加子节点, 多级目录用 / 分隔">
                    <template #prepend>{{ insertForm.prefix }}</template>
                </el-input>
            </el-form-item>
            <el-form-item label="value" prop="value" v-if="!insertForm.dir">
                <el-input v-model="insertForm.value" placeholder="示例 htt8080 "/>
            </el-form-item>
            <el-form-item label="lease" prop="lease">
                <el-input v-model="insertForm.lease" placeholder="0 "/>
            </el-form-item>
        </el-form>
        <template #footer>
            <div style="display: flex; justify-content: space-between; align-items: center;">
                <div>
                    <el-button @click="insertDialog = false">取消</el-button>
                    <el-button type="primary" @click="confirmInsert">确定</el-button>
                </div>
            </div>
        </template>
    </el-dialog>
</template>

<script lang="ts" setup>
import {onMounted, ref, h, defineProps} from "vue";
import {ElMessage, ElMessageBox} from 'element-plus'
import type {Action} from 'element-plus'
import {versionEtcd, kv_range, kv_put, kv_delete, auth_authenticate} from "@/api/etcd3.js"
import {Search} from "@element-plus/icons-vue";
import {Base64} from 'js-base64';

const props = defineProps({
    connect: {
        type: Object,
        default: {
            name: '默认标题',
            url: 'http://127.0.0.1:2379',
            version: 'v2',
            username: 'root',
            password: '123456'
        }
    }
})

const emit = defineEmits(['click-row']);
const handleRowClick = (row, column, event) => {
    emit('click-row', row);
};

const startDetail = (row) => {
    emit('click-row', row);
}

// const store = useEtcdStore()
interface Node {
    dir?: boolean
    key: string
    name: string
    value: string
    ttl: string
    createdIndex: string
    modifiedIndex: string
    // hasChildren?: boolean
    children?: Node[]
}

const tableData = ref([])

function treefy(nodes, parentPrefix) {
    if (Array.isArray(nodes)) {
        for (let i = 0; i < nodes.length; i++) {
            let iterator = nodes[i];
            iterator.key = Base64.decode(iterator.key);
            iterator.name = iterator.key;
            if(!!iterator.value){
                iterator.value = Base64.decode(iterator.value);
            }
        }
        nodes.sort((a, b) => {return a.key.localeCompare(b.key);})
    }
    return nodes;
}

/********* 新增 ********/
const insertDialog = ref(false)
const insertForm = ref({
    prefix: '',
    showName: true,
    name: '',
    showDir: true,
    dir: false,
    value: '',
    lease:null,
})

function startInsert(prefix) {
    insertForm.value.prefix = prefix;
    insertForm.value.showName = true;
    insertForm.value.name = '';
    insertForm.value.showDir = true;
    insertForm.value.dir = false;
    insertForm.value.value = '';
    insertForm.value.lease = null;
    insertDialog.value = true;
}

function confirmInsert() {
    let key = insertForm.value.name;
    let value = insertForm.value.value;
    let lease = insertForm.value.lease;
    let url = props.connect.url;
    let data = {
        "key":Base64.encode(key),
        "value":Base64.encode(value),
        "lease":lease
    }
    kv_put(url, data)
        .then((response) => {
            search();
            insertDialog.value = false;
        })
        .catch((reason) => {
            insertDialog.value = false;
            let error = reason.response.data;
            let message = error.cause + ' ' + error.message;
            ElMessage.error(message)
        });
}

function startEdit(row) {
    let key = row.key;
    insertForm.value.prefix = key.replace(row.name, '')
    insertForm.value.showName = false;
    insertForm.value.name = row.name;
    insertForm.value.showDir = false;
    insertForm.value.dir = !!row.dir;
    insertForm.value.value = row.value;
    insertDialog.value = true;
    console.log('edit', insertForm.value)
}

function startDelete(row) {
    ElMessageBox.confirm(
        'Permanently delete the node. Continue?',
        'Warning',
        {
            confirmButtonText: 'OK',
            cancelButtonText: 'Cancel',
            type: 'warning',
        }
    )
        .then(() => {
            confirmDelete(row);
        })
        .catch(() => {
            // do nothing
        })
}

function confirmDelete(row) {
    const params = new URLSearchParams();
    params.append('recursive', true + '');
    let url = props.connect.url;
    let version = props.connect.version;
    kv_delete(url, row.key)
        .then(response => {
            search();
        })
        .catch(error => {
            let message = error.response.data.message;
            ElMessage.error('kv_delete ' + message);
        });
}


const searchPrefix = ref('');
const searchLimit = ref(100);
const searchLimitOptions = ref([
    {
        key: '50',
        value: '50',
        label: '50',
    },
    {
        key: '100',
        value: '100',
        label: '100',
    },
    {
        key: '1000',
        value: '1000',
        label: '1000',
    },
    {
        key: '10000',
        value: '10000',
        label: '10000',
    },
])

function search() {
    let url = props.connect.url;
    let version = props.connect.version;
    let auth = {user: props.connect.username, password: props.connect.password}
    let data = {"key": Base64.encode('\0'), "range_end": Base64.encode('\0'), "limit": searchLimit.value}
    if (!!searchPrefix.value) {
        data = {
            "key": Base64.encode(searchPrefix.value),
            "range_end": Base64.encode(shiftLastChar(searchPrefix.value)),
            "limit": searchLimit.value
        }
    }
    kv_range(url, data)
        .then(response => {
            console.log('kv_range success');
            let count = response.data.count;
            let kvs = response.data.kvs;
            let tree = treefy(kvs, '')
            tableData.value = tree;
        })
        .catch(error => {
            let message = error.message || error.response.data.message;
            ElMessage.error('kv_range ' + message);
        })
}

function shiftLastChar(str) {
    if (str.length === 0) {
        return str;
    }
    let lastChar = str[str.length - 1];
    let lastCharAscii = lastChar.charCodeAt(0);
    let shiftedAscii = lastCharAscii + 1;
    let shiftedChar = String.fromCharCode(shiftedAscii);
    return str.slice(0, str.length - 1) + shiftedChar;
}

onMounted(() => {
    search();
})

</script>
<style scoped>
.el-icon-folder-opened {
    color: #409EFF;
}

.el-icon-document {
    color: #67C23A;
}
</style>